//==============================================================================
//
//               Copyright (C) 2004  Dick van Oudheusden
//  
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this program; if not, write to the Free
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//==============================================================================
// 
//  $Date: 2004-02-01 08:43:01 $ $Revision: 1.2 $
//
//==============================================================================

#include <stdlib.h>

#include "ofc/config.h"

#include "ofc/DConfig.h"

#include "ofc/DFile.h"

#include "DInc.h"
#include "DTest.h"

//-Misc------------------------------------------------------------------------

#ifdef HAVE_DCONFIG

static char name[]     = "test.ini";

static char comment1[] = "This is a test file for the config writer/reader/tree";
static char comment2[] = "Next: section switch without section method";
static char comment3[] = "End of config file";

static char section1[] = "first";
static char section2[] = "second";
static char section3[] = "third";
static char option11[] = "startup";
static char option21[] = "path";
static char option22[] = "home";
static char option23[] = "server";
static char option31[] = "chapter";
static char option32[] = "paragraph";
static char value11[]  = "yes";
static char value21[]  = "home";
static char value22[]  = "root";
static char value23[]  = "no";
static char value31[]  = "title";
static char value32[]  = "conclusion";


@interface DConfigTest : Object <DConfigHandler>
{
@private
  int    _counter; // the check counter
  DText *_section; // the current section
}

- (DConfigTest *) init;
- free;
- (BOOL) startConfig;
- (BOOL) endConfig;
- (BOOL) section :(const char *) name;
- (BOOL) option :(const char *) section :(const char *) name :(const char *) value;
- (BOOL) comment :(const char *) comment;
- (void) error :(int) number :(const char *) name :(int) lineNumber :(int) columnNumber;
        
@end


@implementation DConfigTest 


- (DConfigTest *) init
{
  [super init];

  _counter = 0;
  _section = [DText new];
  
  return self;
}


- free
{
  [_section free];
  
  return [super free];
}

- (BOOL) startConfig
{
  TEST(_counter == 0);
  
  _counter++;
 
  return YES;
}

- (BOOL) endConfig
{
  TEST(_counter == 10);
  
  _counter++;
  
  return YES;
}

- (BOOL) section :(const char *) name
{
  switch (_counter)
  {
    case 2: TEST(strcmp(name, section1) == 0); break;
    case 5: TEST(strcmp(name, section2) == 0); break;
    default: TEST(NO); break;
  }
  
  [_section set :name];

  _counter++;
  
  return YES;
}

- (BOOL) option :(const char *) section :(const char *) name :(const char *) value
{
  TEST([_section icompare :section] == 0);
  
  switch (_counter)
  {
   case 3: TEST((strcmp(name, option11) == 0) && (strcmp(value, value11) == 0)); break;
   case 6: TEST((strcmp(name, option21) == 0) && (strcmp(value, value21) == 0)); break;
   case 7: TEST((strcmp(name, option22) == 0) && (strcmp(value, value22) == 0)); break;
   case 8: TEST((strcmp(name, option23) == 0) && (strcmp(value, value23) == 0)); break;
   default: TEST(NO); printf("Counter:%d\n", _counter); break;
  }
  _counter++;
  

  return YES;
}
    
- (BOOL) comment :(const char *) comment
{
  switch (_counter)
  {
   case 1:  TEST(strcmp(comment, comment1) == 0); break;
   case 4:  TEST(strcmp(comment, comment2) == 0); break;
   case 9:  TEST(strcmp(comment, comment3) == 0); break;
   default: TEST(NO); break;
  }
  
  _counter++;
  
  return YES;
}

- (void) error :(int) number :(const char *) name :(int) lineNumber :(int) columnNumber;
{
  TEST(NO);

  _counter++;
}
        
@end

#endif

void DConfig_test()
{
#ifdef HAVE_DCONFIG
  DConfigWriter *writer = [DConfigWriter new];
  DConfigReader *reader = [DConfigReader new];
  DConfigTree   *tree   = [DConfigTree   new];
  DConfigTest   *tester = [DConfigTest   new];
  const char    *text;
  
  DFile         *file   = [DFile new];
  BOOL           ok;
  DList         *list;
  
  [file open :name :"w"];
  
  STARTTEST();

  // Test of the config writer
  
  TEST([writer startConfig :file]);
  
  TEST([writer comment :comment1]);

  [file writeLine :""];
  
  TEST([writer section :section1]);
  TEST([writer option  :section1 :option11 :value11]);
  
  [file writeLine :"                       "];
  
  TEST([writer comment :comment2]);
  
  TEST([writer option  :section2 :option21 :value21]);
  TEST([writer option  :section2 :option22 :value22]);
  TEST([writer option  :section2 :option23 :value23]);
  
  [file writeLine :"\t"];
  
  TEST([writer comment :comment3]);
  
  TEST([writer endConfig]);
  
  [file  close];
  [writer free];
  
  // Test of the config reader
  ok = [file open :name :"r"];
  
  TEST(ok);
  if (ok)
  {
    TEST([reader parse :file :name :tester]);
    
    [file close];
  }
  [reader free];
  [tester free];
  
  ok = [file open :name :"r"];
  
  TEST(ok);
  
  if (ok)
  {
    TEST([tree read :file :name]);
    
    TEST( [tree has :section1 ]);
    TEST(![tree has :"unknown"]);
    
    TEST( [tree has :section2 :option23 ]);
    TEST(![tree has :section2 :"unknown"]);
    
    text = [tree get :section2 :option22];
    
    TEST(text != NULL);
    
    TEST(strcmp(text, value22) == 0);
    
    text = [tree get :section1 :option21];
    
    TEST(text == NULL);
    
    
    TEST([tree set :section3 :option31 :value31]);
    TEST([tree set :section3 :option32 :value32]);
    
    TEST(![tree remove :section2 :"unknown"]);
    TEST( [tree remove :section2 :option22  ]);
    
    TEST(![tree has :section2 :option22]);
    
    TEST( [tree remove :section2]);
    
    TEST(![tree has :section2 :option23]);
    TEST(![tree has :section2]);
    
    TEST( [tree has :section3]);
    
    
    list = [tree sections];
    
    TEST(list != nil);
    TEST([list length] == 2);
    
    [list free];
    
    list = [tree options :section2];
    
    TEST(list == nil);
    
    list = [tree options :section3];
    
    TEST(list != nil);
    
    TEST([list length] == 2);
    
    [list free];
    
    [file close];
  }
  
  ok = [file open :name :"w"];

  TEST(ok);
  
  if (ok)
  {
    TEST([tree write :file :name]);
    
    [file close];
  }
  [tree free];
  
  [file free];
    
  STOPTEST();
#endif
}

